package com.winchain.chainbill.bill.biz.discount.controller;

import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.acct.account.po.AcctBkp;
import com.shell.bee.acct.account.po.AcctCard;
import com.shell.bee.acct.account.util.VirtualAcctUtil;
import com.shell.bee.base.annotation.Logging;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.invoince.po.InvDfr;
import com.shell.bee.invoince.service.InvDfrService;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.constant.rel.AssetCode;
import com.shell.customer.feign.CustomerFeign;
import com.shell.customer.po.CusTag;
import com.shell.feign.PubDateFeign;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.CommonFileUtil;
import com.shell.framework.utils.ParameterHelper;
import com.shell.governor.modules.vo.ParameterVo;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.basic.activity.service.BasCusCpnService;
import com.winchain.chainbill.basic.activity.vo.BasCusCpnVo;
import com.winchain.chainbill.basic.charge.service.ValComService;
import com.winchain.chainbill.basic.charge.vo.ValComVo;
import com.winchain.chainbill.basic.cus.po.CusRec;
import com.winchain.chainbill.basic.cus.service.CusGrpService;
import com.winchain.chainbill.basic.cus.service.CusRecService;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbDctOverdue;
import com.winchain.chainbill.bill.base.po.CbDctQt;
import com.winchain.chainbill.bill.base.po.CbDctRpmt;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.base.service.CbAttService;
import com.winchain.chainbill.bill.base.service.CbDctOverdueService;
import com.winchain.chainbill.bill.base.service.CbDctQtService;
import com.winchain.chainbill.bill.base.service.CbDctRpmtService;
import com.winchain.chainbill.bill.biz.discount.service.BillDctAprvService;
import com.winchain.chainbill.bill.biz.discount.service.BillDctQueryService;
import com.winchain.chainbill.bill.biz.discount.service.BillDctRevService;
import com.winchain.chainbill.bill.biz.discount.service.BillDctService;
import com.winchain.chainbill.bill.biz.discount.vo.BillDct;
import com.winchain.chainbill.bill.biz.query.service.BillQueryService;
import com.winchain.chainbill.bill.biz.query.vo.CbRecQueryVo;
import com.winchain.chainbill.bill.biz.query.vo.CbRecVo;
import com.winchain.chainbill.bill.biz.send.vo.BatchBillStats;
import com.winchain.chainbill.bill.biz.transfer.service.BillXfeService;
import com.winchain.chainbill.risk.utill.RateUtil;
import com.winchain.chainbill.trade.service.BillAcctBlcService;
import com.winchain.chainbill.trade.service.BillAcctService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class BillDctController {
	@Autowired
	BillQueryService billQueryService;
	@Autowired
	BillDctQueryService billDctQueryService;
	@Autowired
	BillDctService billDctService;
	@Autowired
	BillDctRevService billDctRevService;
	@Autowired
	CusRecService cusRecService;
	@Autowired
	CusGrpService cusGrpService;
	@Autowired
	BillAcctService billAcctService;
	@Autowired
	PubDateFeign dateFeign;
	@Autowired
	private CbDctQtService cbDctQtService;
	@Autowired
	private CustomerFeign customerFeign;
	@Autowired
	private BasCusCpnService basCusCpnService;
	@Autowired
	private ValComService valComService;
	@Autowired
	private CbAttService cbAttService;
	@Autowired
	private BillXfeService billXfeService;
	@Autowired
	private BillDctAprvService billDctAprvService;
	@Autowired
	private InvDfrService invDfrService;
	@Autowired
	private BillAcctBlcService billAcctBlcService;
	@Autowired
	private CbDctRpmtService cbDctRpmtService;
	@Autowired
	private CbDctOverdueService cbDctOverdueService;

	private List<Map<String, Object>> getFinAndRate(CbRecVo bill) {
		List<Map<String, Object>> list = new ArrayList();
		String tagCodes = "FIN_BUYER,FIN_SELLER";
		List<CusRec> finners = this.cusGrpService.findGroupEnts(bill.getGrpId(), tagCodes);
		CbDctQt dctQt = null;
		List<CusTag> cusTags = null;
		for (CusRec rec : finners) {
			Map<String, Object> m = new HashMap();

			AcctBkp bkp = this.billAcctBlcService.getCreditAcctBkpByCont(rec.getCusId(), bill.getSenderId(),
					AssetCode.FQT.name(), "42");
			if ((bkp != null) && ("1".equals(bkp.getQuotaState()))) {
				BigDecimal fqtAvailAmt = bkp.getAcctBlc().subtract(bkp.getAcctBlk());
				m.put("fqtAmt", bkp.getAcctAmt());
				m.put("fqtBlc", bkp.getAcctBlc());
				m.put("fqtBlk", bkp.getAcctBlk());
				m.put("fqtAvailAmt", fqtAvailAmt);

				String dctFixedRate = RateUtil.getFixedRate(bill.getGrpId(), rec.getCusId(), "dct_fixed_rate");
				String dctVariableRate = RateUtil.getVariableRate(bill.getGrpId(), rec.getCusId(), bill.getSenderId(),
						"dct_variable_rate");
				String dctEntVariableRate = RateUtil.getEntVariableRate(bill.getGrpId(), bill.getGrpId(),
						CommonDataUtil.getCurEntId(), "dct_ent_variable_rate");
				String dctEntVariableRateFin = RateUtil.getEntVariableRate(bill.getGrpId(), rec.getCusId(),
						CommonDataUtil.getCurEntId(), "dct_ent_variable_rate");
				if (StringUtil.empty(dctEntVariableRate)) {
					dctEntVariableRate = dctEntVariableRateFin;
				}
				String dctRatio = RateUtil.getEntDctRate(bill.getGrpId(), bill.getGrpId(), bill.getSenderId(),
						"ent_tb_dct_rate");
				if (StringUtil.emptyAndNull(dctRatio)) {
					dctRatio = RateUtil.getDctRate(rec.getCusId(), rec.getCusId(), rec.getCusId(), "tb_dct_rate");
				}
				String ivUploadLimitDay = RateUtil.getInvoiceUploadLimitDays(bill.getGrpId(), bill.getGrpId(),
						bill.getSenderId(), "iv_upload_limit_day");

				String ivUploadGracePeriod = RateUtil.getInvoiceUploadGracePeriod(bill.getGrpId(), bill.getGrpId(),
						bill.getSenderId(), "iv_upload_grace_period");
				cusTags = this.customerFeign.getCusTagForEnt(rec.getCusId(), bill.getGrpId());
				String tagCode = null;
				for (CusTag cusTag : cusTags) {
					if ("FIN_BUYER".equals(cusTag.getTagCode())) {
						tagCode = cusTag.getTagCode();
						break;
					}
					if ("FIN_SELLER".equals(cusTag.getTagCode())) {
						tagCode = cusTag.getTagCode();
					}
				}
				m.put("tagCode", tagCode);

				ValComVo serviceFee = this.valComService.getDctValComVo(rec.getCusId(), bill.getGrpId());
				if ((serviceFee != null) && ("1".equals(serviceFee.getPayBy()))) {
					m.put("dctSerFeeRate", serviceFee.getValStd());
					m.put("dctSerFeeMin", serviceFee.getValMin());
					m.put("dctSerFeeMax", serviceFee.getValMax());
				}
				m.put("finId", rec.getCusId());
				m.put("finNm", rec.getCusName());
				m.put("dctFixedRate", dctFixedRate);
				m.put("dctVariableRate", dctVariableRate);
				m.put("dctEntVariableRate", dctEntVariableRate);
				m.put("dctRatio", dctRatio);
				m.put("ivUploadLimitDay", ivUploadLimitDay);
				m.put("ivUploadGracePeriod", ivUploadGracePeriod);

				BasCusCpnVo tmp = new BasCusCpnVo();
				tmp.setCusId(CommonDataUtil.getCurEntId());
				tmp.setIssuer(rec.getCusId());
				List<BasCusCpnVo> cpns = this.basCusCpnService.selectCusCpns(tmp);
				boolean hasCpn = false;
				if ((cpns != null) && (cpns.size() > 0)) {
					hasCpn = true;
				}
				m.put("hasCpn", Boolean.valueOf(hasCpn));

				list.add(m);
			}
		}
		return list;
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������������")
	public Map<String, Object> getInitData(String billId) {
		CbRecVo bill = this.billQueryService.selectBillDetail(billId);

		CbXfe xfe = this.billXfeService.selectOne(bill.getBillId(), bill.getHldrLvl(), bill.getHldrId());
		if (xfe != null) {
			bill.setDctBillId(xfe.getBillId());
			bill.setBizId(xfe.getXfeId());
		} else {
			bill.setDctBillId(bill.getBillId());
			bill.setBizId(bill.getSendBillId());
		}
		this.cbAttService.setAtt(bill);

		ParameterVo dctNeedInterest = ParameterHelper.getCommonParameter("DCT_NEED_INTEREST");

		ParameterVo vo = ParameterHelper.getParameter("6", "DCT_MIN_INT", bill.getGrpId());
		ParameterVo blTimes = ParameterHelper.getParameter("6", "DCT_LIM_BL_TIM", bill.getGrpId());

		ParameterVo rateMParams = ParameterHelper.getParameter("6", "DCT_RATE_MODE", bill.getGrpId());
		String acctType = null;
		if ((ChainBillUtil.onlinePay()) && (VirtualAcctUtil.onVirtual())) {
			acctType = "1";
		} else {
			acctType = "0";
		}
		List<AcctCard> accts = this.billAcctService.getCards(CommonDataUtil.getCurEntId(), acctType);

		Map<String, Object> ret = new HashMap();
		List<Map<String, Object>> finners = getFinAndRate(bill);
		ret.put("bill", bill);
		ret.put("finners", finners);
		ret.put("accts", accts);
		ret.put("dctNeedInterest", dctNeedInterest);
		ret.put("allHoliday", this.dateFeign.getHoliday("", ""));

		ret.put("showSellerAcct", Boolean.valueOf((ChainBillUtil.onlinePay()) && (VirtualAcctUtil.onVirtual())));
		if (vo != null) {
			ret.put("dctMinInt", vo.getParmValue());
		}
		if ((blTimes != null) && (!StringUtil.emptyAndNull(blTimes.getParmValue()))) {
			ret.put("blTimes", blTimes.getParmValue());
		}
		if ((rateMParams == null) || (StringUtil.emptyAndNull(rateMParams.getParmValue()))) {
			ret.put("rateMode", "2");
		} else {
			ret.put("rateMode", rateMParams.getParmValue());
		}
		return ret;
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������������")
	public CbRecVo getRooBillForDawn(String billId) {
		return this.billQueryService.selectBillDetailForAll(billId);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������")
	public RetMsg dct(String billId, String phoneCode, String location, CbDct dct, String attInvoicesJson)
			throws Exception {
		String txSnHost = this.billDctService.dct(billId, phoneCode, location, dct, attInvoicesJson);
		return new RetMsg("success", false, "����������", txSnHost);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public RetMsg reviewPass(String phoneCode, String location, String billIds) throws Exception {
		if (StringUtil.emptyAndNull(billIds)) {
			new RetMsg("error", false, "��������");
		}
		String[] billIdArr = billIds.split(",");
		BatchBillStats<CbDct> stats = this.billDctRevService.pass(true, phoneCode, location, billIdArr);
		if (billIdArr.length == stats.getAffectedRows()) {
			return new RetMsg("success", false, "������������������������������2��������������������������������",
					stats.getTxSnHost());
		}
		if (stats.getAffectedRows() == 0) {
			return new RetMsg("error", false, "������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
		}
		if (stats.getAffectedRows() == -1) {
			return new RetMsg("error", false, "��������������������������");
		}
		return new RetMsg("warning", false, "����������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public RetMsg reviewReject(String remark, String billIds) throws Exception {
		if (StringUtil.emptyAndNull(billIds)) {
			new RetMsg("error", false, "��������");
		}
		String[] billIdArr = billIds.split(",");
		BatchBillStats<CbDct> stats = this.billDctRevService.reject(remark, billIdArr);
		if (billIdArr.length == stats.getAffectedRows()) {
			return new RetMsg("success", false, "����������������������������������");
		}
		if (stats.getAffectedRows() == 0) {
			return new RetMsg("error", false, "����������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
		}
		return new RetMsg("warning", false, "��������������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������")
	public Map<String, Object> getDetail(String billId) {
		CbRecVo bill = this.billQueryService.selectBillDetail(billId);

		CbDct dct = this.billDctQueryService.selectByBillId(billId);
		bill.setBizId(dct.getDctId());
		bill.setDctBillId(dct.getBillId());

		this.cbAttService.setAtt(bill);
		AcctBas acct = this.billAcctService.getCard(dct.getSellerAcct());

		Map<String, Object> ret = new HashMap();
		ret.put("bill", bill);
		ret.put("discount", dct);
		ret.put("sellerAcctName", acct.getFiNm());

		ParameterVo vo = ParameterHelper.getParameter("6", "DCT_MIN_INT", bill.getGrpId());
		if (vo != null) {
			ret.put("dctMinInt", vo.getParmValue());
		}
		ValComVo serviceFee = this.valComService.getDctValComVo(dct.getFinId(), bill.getGrpId());
		if (serviceFee != null) {
			ret.put("payBy", serviceFee.getPayBy());
		}
		InvDfr invDfr = this.invDfrService.selectByBiz(dct.getDctId(), "1");
		boolean showInvoice = true;
		if ((invDfr != null) && (!"1".equals(invDfr.getState()))) {
			showInvoice = false;
		}
		ret.put("showInvoice", Boolean.valueOf(showInvoice));
		if ("S013".equals(bill.getBillState())) {
			AcctBkp bkp = this.billAcctBlcService.getCreditAcctBkpByCont(dct.getFinId(), bill.getSenderId(),
					AssetCode.FQT.name(), "42");
			BigDecimal fqtAvailAmt = bkp.getAcctBlc().subtract(bkp.getAcctBlk());
			ret.put("fqtAmt", bkp.getAcctAmt());
			ret.put("fqtBlc", bkp.getAcctBlc());
			ret.put("fqtBlk", bkp.getAcctBlk());
			ret.put("fqtAvailAmt", fqtAvailAmt);
		}
		CbDctRpmt dctRpmt = this.cbDctRpmtService.selectDctRpmtByBizIdAndType(dct.getDctId(), "1");
		if (dctRpmt != null) {
			ret.put("dctRpmt", dctRpmt);
		}
		CbDctOverdue dctOverdue = this.cbDctOverdueService.selectDctOverdueByBizIdAndType(dct.getDctId(), "1");
		if (dctOverdue != null) {
			ret.put("dctOverdue", dctOverdue);
		}
		return ret;
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������")
	public List<CbRecVo> selectBillForDct(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		return this.billDctQueryService.selectBillForDct(limit, cbRecordQueryVo);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public List<BillDct> selectBillForDctReviewByPage(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		return this.billDctQueryService.selectBillForDctReviewByPage(limit, cbRecordQueryVo);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public List<BillDct> selectBillForDctApproveByPage(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		return this.billDctQueryService.selectBillForDctApproveByPage(limit, cbRecordQueryVo);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "����������������")
	public List<BillDct> selectDctBillForPaidByPage(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		return this.billDctQueryService.selectDctBillForPaid(limit, cbRecordQueryVo);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������������������")
	public List<BillDct> selectDctBillForPrePaidByPage(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		return this.billDctQueryService.selectDctBillForPrePaid(limit, cbRecordQueryVo);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public RetMsg paidConfirm(String phoneCode, String location, String billIds, String pmtDate, BigDecimal recvAmt,
			BigDecimal dctInt, String dctDays) throws Exception {
		if (StringUtil.emptyAndNull(billIds)) {
			new RetMsg("error", false, "��������");
		}
		String[] billIdArr = billIds.split(",");
		BatchBillStats<CbDct> stats = this.billDctRevService.paidConfirm(phoneCode, location, pmtDate, recvAmt, dctInt,
				dctDays, billIdArr);
		if (billIdArr.length == stats.getAffectedRows()) {
			return new RetMsg("success", false, "������������������", stats.getTxSnHost());
		}
		if (stats.getAffectedRows() == 0) {
			return new RetMsg("error", false, "����������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
		}
		return new RetMsg("warning", false, "��������������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public RetMsg approvePass(String phoneCode, String location, String billIds) throws Exception {
		if (StringUtil.emptyAndNull(billIds)) {
			new RetMsg("error", false, "��������");
		}
		String[] billIdArr = billIds.split(",");
		BatchBillStats<CbDct> stats = this.billDctAprvService.pass(phoneCode, location, billIdArr);
		if (billIdArr.length == stats.getAffectedRows()) {
			return new RetMsg("success", false, "��������", stats.getTxSnHost());
		}
		if (stats.getAffectedRows() == 0) {
			return new RetMsg("error", false, "������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
		}
		if (stats.getAffectedRows() == -1) {
			return new RetMsg("error", false, "��������������������������");
		}
		return new RetMsg("warning", false, "����������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public RetMsg approveReject(String remark, String billIds) throws Exception {
		if (StringUtil.emptyAndNull(billIds)) {
			new RetMsg("error", false, "��������");
		}
		String[] billIdArr = billIds.split(",");
		BatchBillStats<CbDct> stats = this.billDctAprvService.reject(remark, billIdArr);
		if (billIdArr.length == stats.getAffectedRows()) {
			return new RetMsg("success", false, "������������������������������������");
		}
		if (stats.getAffectedRows() == 0) {
			return new RetMsg("error", false, "����������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
		}
		return new RetMsg("warning", false, "��������������������", CommonFileUtil.changMsg(stats.getAbnormalMsg()));
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������������")
	public List<BillDct> selectUnuploadInvoiceListByPage(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		return this.billDctQueryService.selectUnuploadInvoiceListByPage(limit, cbRecordQueryVo);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public RetMsg uploadInvoices(String dctId, String attInvoicesJson) throws Exception {
		if ((StringUtil.emptyAndNull(dctId)) || (StringUtil.emptyAndNull(attInvoicesJson))) {
			return new RetMsg("error", true, "����������");
		}
		this.billDctService.uploadInvoices(dctId, attInvoicesJson);
		return new RetMsg("success", false, "��������������");
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "������������")
	public List<BillDct> getBillForDctMgt(PageLimit limit, CbRecQueryVo cbRecordQueryVo) {
		cbRecordQueryVo.setBillStates(new String[] { "S012", "S018" });
		cbRecordQueryVo.setRpmtType("1");
		return this.billDctQueryService.selectBillForDctMgtByPage(limit, cbRecordQueryVo);
	}
}
